import java.util.LinkedList;

public class MinNode extends Node {

    int beta;

    public MinNode(int[][] board) {
        for (int k = 0; k < 3; k++) {
            System.arraycopy(board[k], 0, this.board[k], 0, 3);
        }
        this.beta = Game.UNKNOWN_INT;
    }

    public MinNode(int[][] board, int i, int j) {
        board[i][j] = 1;
        for (int k = 0; k < 3; k++) {
            System.arraycopy(board[k], 0, this.board[k], 0, 3);
        }
        pre_i = i;
        pre_j = j;
        this.beta = Game.UNKNOWN_INT;
        board[i][j] = 0;
    }

    @Override
    public void evaluateF() {//评估函数
        if (_F != null) return;
        //player win
        if (isWin()) _F = Game.MAX_INT;
        else {
            //预测杀局
            predictDeath();
            if (_F == null)
                super.evaluateF();
        }
    }

    //重置节点的一些数据，消去对再次访问的影响
    @Override
    void reset() {
        beta = Game.UNKNOWN_INT;
        super.reset();
    }

    @Override
    void play(int depth, int parentAlpha, int parentBeta) {
        reset();
//        printBoard(board);
        if (isWin() || isFull() || depth == 0) {
            evaluateF();
//            System.out.println("evaluate F:"+_F);
            return;
        }

        extend();
        //判断当前局面
        predictDeath();
        //走一步就胜利
        if (_F != null && _F == Game.MIN_INT) {
            for (Node maxNode : childNodes) {
                if (maxNode.isWin()) {
                    nextNode = maxNode;
                    break;
                }
            }
            return;
        }
        for (Node maxNode : childNodes) {
            maxNode.play(depth - 1, parentAlpha, parentBeta);
            //倒推beta值
            if (beta != Game.UNKNOWN_INT && beta >= maxNode._F || beta == Game.UNKNOWN_INT) {
                //增加对值相等情况的判断
                if (beta == maxNode._F) {
                    maxNode.predictDeath();
                    //死局
                    if (maxNode._F != null && maxNode._F == Game.MIN_INT) {
                        _F = Game.MIN_INT;
                        nextNode = maxNode;
                        return;
                    } else continue;
                }
                nextNode = maxNode;
                beta = maxNode._F;
                //成杀局
                if (beta == Game.MIN_INT) {
                    break;
                }
                if ((parentBeta == Game.UNKNOWN_INT)) {
                    parentBeta = beta;
                } else {
                    if ((parentBeta > beta)) {
                        parentBeta = beta;
                    }
                }
//                System.out.println("update beta:"+beta);
            }
            //alpha cut
            if (parentAlpha != Game.UNKNOWN_INT && beta <= parentAlpha) {
//                logger.info("min alpha cut .F: "+_F);
//                System.out.println("alpha cut:"+beta+"<="+parentAlpha+" depth: "+depth);
                break;
            }
        }
        _F = beta;
//        System.out.println("no cut set min F:"+_F+" depth: "+depth);
//        logger.info("no cut .F: "+_F);
    }

    @Override
    void extend() {
        if (childNodes == null) {
            childNodes = new LinkedList<Node>();

            //优化初始个数为0的扩展方式
            if (getChessCount() == 0) {
                childNodes.add(new MaxNode(board, 0, 0));
                childNodes.add(new MaxNode(board, 1, 0));
                childNodes.add(new MaxNode(board, 1, 1));
                return;
            }
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    if (this.board[i][j] == 0) {
                        childNodes.add(new MaxNode(board, i, j));
                    }
                }
            }
        }
    }

    @Override
    void predictDeath() {
        int count = getComputerVitalCount();
        //computer go will win
        if (count > 0) _F = Game.MIN_INT;
        else {
            count = getPlayerVitalCount();
            //computer will win
            if (count > 1) _F = Game.MAX_INT;
        }
    }
}